#pragma once
#include <sys/epoll.h>
#include "Log.hpp"

// 对epoll的封装
namespace EpollModule
{
    using namespace LogModule;

    const static int g_epoll_defaultfd = -1;

    enum Status
    {
        OK,
        EPOLLCREATEFAIL,
        EPOLLWAITFAIL
    };
    
    class Epoll
    {
    private:
        bool Ctl(int op, int fd, uint32_t events)
        {
            struct epoll_event ev;
            ev.events = events;
            ev.data.fd = fd;
            return epoll_ctl(_epollfd,op,fd,&ev) == 0;
        }
    public:
        Epoll():_epollfd(g_epoll_defaultfd)
        {}
        void Init()
        {
            _epollfd = ::epoll_create(256);
            if(_epollfd < 0)
            {
                LOG(LogLevel::FATAL) << "epoll init failed!";
                exit(EPOLLCREATEFAIL);
            }
            LOG(LogLevel::INFO) << "epoll create success, epollfd is " << _epollfd;
        }
        int Wait(struct epoll_event* events, int eventsnum, int timeout)
        {
            int n = epoll_wait(_epollfd, events, eventsnum, timeout);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "epoll wait failed!";
                exit(EPOLLWAITFAIL);
            }
            return n;
        }
        void AddCtl(int fd, uint32_t events)
        {
            if(!Ctl(EPOLL_CTL_ADD,fd,events))
            {
                LOG(LogLevel::FATAL) << "epoll addctl failed!";
            }
        }
        void ModCtl(int fd, uint32_t events)
        {
            if(!Ctl(EPOLL_CTL_MOD,fd,events))
            {
                LOG(LogLevel::FATAL) << "epoll modctl failed!";
            }
        }
        void DelCtl(int fd)
        {
            if(!Ctl(EPOLL_CTL_DEL,fd,0))
            {
                LOG(LogLevel::FATAL) << "epoll delctl failed!";
            }
        }
        ~Epoll()
        {}
    private:
        int _epollfd;
    };
}